package org.cybzacg.convert.strategy.impl;


import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.core.TypeConverter;
import org.cybzacg.convert.enums.ConversionError;
import org.cybzacg.convert.enums.ConversionStrategyEnum;
import org.cybzacg.convert.exception.ConversionException;
import org.cybzacg.convert.strategy.ConversionStrategy;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 性能优先转换策略
 * 优化转换性能，使用快速路径和缓存机制，可能牺牲一些准确性
 *
 * @author cybzacg.blog
 * @version 3.0
 * @since 3.0
 */
@Slf4j
public class PerformanceConversionStrategy implements ConversionStrategy {

    // 简单转换结果缓存
    private static final Map<String, Object> conversionCache = new ConcurrentHashMap<>();
    
    // 缓存大小限制
    private static final int MAX_CACHE_SIZE = 1000;
    
    // 简单类型集合，用于快速路径判断
    private static final Class<?>[] SIMPLE_TYPES = {
        String.class, Integer.class, Long.class, Double.class, Float.class,
        Boolean.class, Short.class, Byte.class, Character.class,
        int.class, long.class, double.class, float.class,
        boolean.class, short.class, byte.class, char.class
    };

    @Override
    public <T> T execute(
            TypeConverter converter,
            Object source,
            Class<T> targetType,
            T defaultValue,
            ConversionContext context
    ) throws ConversionException {

        // 性能优化：快速路径处理简单类型
        if (isSimpleConversion(source, targetType)) {
            return fastConvert(source, targetType, defaultValue);
        }

        // 性能优化：检查缓存
        String cacheKey = generateCacheKey(source, targetType);
        if (cacheKey != null) {
            @SuppressWarnings("unchecked")
            T cachedResult = (T) conversionCache.get(cacheKey);
            if (cachedResult != null) {
                log.debug("命中缓存: {} -> {}", 
                    source != null ? source.getClass().getSimpleName() : "null",
                    targetType.getSimpleName());
                return cachedResult;
            }
        }

        try {
            // 执行转换
            T result = converter.convert(source, targetType, defaultValue, context);

            // 性能优化：缓存简单转换结果
            if (cacheKey != null && shouldCache(result)) {
                cacheResult(cacheKey, result);
            }

            return result;

        } catch (ConversionException e) {
            // 性能模式下，对于ConversionException直接抛出
            log.debug("性能模式下转换失败: {} -> {}, 错误: {}",
                    source, targetType.getSimpleName(), e.getMessage());
            throw e;

        } catch (Exception e) {
            // 性能模式下，对于其他异常快速处理
            log.debug("性能模式下转换异常，使用默认值: {} -> {}, 错误: {}",
                    source, targetType.getSimpleName(), e.getMessage());
            
            // 性能优先，直接返回默认值，不做复杂的异常处理
            return defaultValue;
        }
    }

    /**
     * 快速转换路径
     */
    @SuppressWarnings("unchecked")
    private <T> T fastConvert(Object source, Class<T> targetType, T defaultValue) {
        try {
            // 空值快速处理
            if (source == null) {
                return defaultValue;
            }

            // 相同类型快速返回
            if (targetType.isInstance(source)) {
                return (T) source;
            }

            // 字符串到基本类型的快速转换
            if (source instanceof String) {
                String strValue = (String) source;
                if (strValue.isEmpty()) {
                    return defaultValue;
                }

                // 快速字符串转换
                return fastStringConvert(strValue, targetType, defaultValue);
            }

            // 数字类型之间的快速转换
            if (isNumericType(source.getClass()) && isNumericType(targetType)) {
                return fastNumericConvert(source, targetType, defaultValue);
            }

        } catch (Exception e) {
            log.debug("快速转换失败，使用默认值: {}", e.getMessage());
        }

        return defaultValue;
    }

    /**
     * 快速字符串转换
     */
    @SuppressWarnings("unchecked")
    private <T> T fastStringConvert(String strValue, Class<T> targetType, T defaultValue) {
        try {
            if (targetType == String.class) {
                return (T) strValue;
            } else if (targetType == Integer.class || targetType == int.class) {
                return (T) Integer.valueOf(strValue);
            } else if (targetType == Long.class || targetType == long.class) {
                return (T) Long.valueOf(strValue);
            } else if (targetType == Double.class || targetType == double.class) {
                return (T) Double.valueOf(strValue);
            } else if (targetType == Float.class || targetType == float.class) {
                return (T) Float.valueOf(strValue);
            } else if (targetType == Boolean.class || targetType == boolean.class) {
                return (T) Boolean.valueOf(strValue);
            } else if (targetType == Short.class || targetType == short.class) {
                return (T) Short.valueOf(strValue);
            } else if (targetType == Byte.class || targetType == byte.class) {
                return (T) Byte.valueOf(strValue);
            } else if (targetType == Character.class || targetType == char.class) {
                if (!strValue.isEmpty()) {
                    return (T) Character.valueOf(strValue.charAt(0));
                }
            }
        } catch (NumberFormatException e) {
            log.debug("数字格式错误，使用默认值: {}", strValue);
        }
        return defaultValue;
    }

    /**
     * 快速数字转换
     */
    @SuppressWarnings("unchecked")
    private <T> T fastNumericConvert(Object source, Class<T> targetType, T defaultValue) {
        try {
            Number number = (Number) source;
            
            if (targetType == Integer.class || targetType == int.class) {
                return (T) Integer.valueOf(number.intValue());
            } else if (targetType == Long.class || targetType == long.class) {
                return (T) Long.valueOf(number.longValue());
            } else if (targetType == Double.class || targetType == double.class) {
                return (T) Double.valueOf(number.doubleValue());
            } else if (targetType == Float.class || targetType == float.class) {
                return (T) Float.valueOf(number.floatValue());
            } else if (targetType == Short.class || targetType == short.class) {
                return (T) Short.valueOf(number.shortValue());
            } else if (targetType == Byte.class || targetType == byte.class) {
                return (T) Byte.valueOf(number.byteValue());
            }
        } catch (Exception e) {
            log.debug("数字转换失败，使用默认值: {}", e.getMessage());
        }
        return defaultValue;
    }

    /**
     * 判断是否为简单转换
     */
    private boolean isSimpleConversion(Object source, Class<?> targetType) {
        // 空值转换
        if (source == null) {
            return true;
        }

        Class<?> sourceType = source.getClass();
        
        // 相同类型
        if (targetType.isInstance(source)) {
            return true;
        }

        // 都是简单类型
        if (isSimpleType(sourceType) && isSimpleType(targetType)) {
            return true;
        }

        return false;
    }

    /**
     * 判断是否为简单类型
     */
    private boolean isSimpleType(Class<?> type) {
        for (Class<?> simpleType : SIMPLE_TYPES) {
            if (simpleType == type) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否为数字类型
     */
    private boolean isNumericType(Class<?> type) {
        return type == Integer.class || type == int.class ||
               type == Long.class || type == long.class ||
               type == Double.class || type == double.class ||
               type == Float.class || type == float.class ||
               type == Short.class || type == short.class ||
               type == Byte.class || type == byte.class ||
               Number.class.isAssignableFrom(type);
    }

    /**
     * 生成缓存键
     */
    private String generateCacheKey(Object source, Class<?> targetType) {
        if (source == null || !isSimpleType(source.getClass()) || !isSimpleType(targetType)) {
            return null;
        }
        
        return source.getClass().getSimpleName() + ":" + 
               source.toString() + ":" + targetType.getSimpleName();
    }

    /**
     * 判断是否应该缓存结果
     */
    private boolean shouldCache(Object result) {
        // 只缓存简单类型和字符串
        return result != null && 
               (isSimpleType(result.getClass()) || result instanceof String);
    }

    /**
     * 缓存转换结果
     */
    private void cacheResult(String cacheKey, Object result) {
        // 防止缓存过大
        if (conversionCache.size() >= MAX_CACHE_SIZE) {
            // 简单的清理策略：清除一半缓存
            int targetSize = MAX_CACHE_SIZE / 2;
            conversionCache.entrySet().removeIf(entry -> 
                conversionCache.size() > targetSize);
        }
        
        conversionCache.put(cacheKey, result);
        log.debug("缓存转换结果: {} = {}", cacheKey, result);
    }

    /**
     * 清理缓存
     */
    public static void clearCache() {
        conversionCache.clear();
        log.debug("清理性能转换缓存");
    }

    /**
     * 获取缓存大小
     */
    public static int getCacheSize() {
        return conversionCache.size();
    }

    @Override
    public ConversionStrategyEnum getName() {
        return ConversionStrategyEnum.PERFORMANCE;
    }

    @Override
    public String getDescription() {
        return "性能优先转换策略，优化转换性能，使用快速路径和缓存机制，可能牺牲一些准确性";
    }

    @Override
    public boolean supports(ConversionContext context) {
        return context != null && context.getStrategy().isPerformance();
    }
}
